using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Drawing;
using System.Web;
using System.IO;
using Alogient.Cameleon.Forms.Sdk.Items;
using Alogient.Cameleon.Forms.Sdk.Util;
using System.Resources;

namespace Alogient.Cameleon.Forms.Sdk.Controls
{
    internal class FormUpload : CMFormElement
    {
        protected const string UPLOAD_FORMAT = "{0}{1}_{2}_{3}_{4}"; //Path, FormID, PageID, FormElementID, FileName
        protected const string UPLOAD_ID_FORMAT = "upload_{0}";
        protected const string POSTED_FILE_ID_FORMAT = "PostedFile_{0}";

        public override string Value
        {
            get
            {
                FileUpload upload = this.FindControl(string.Format(UPLOAD_ID_FORMAT, this.ID)) as FileUpload;

                return upload.FileName;
            }
        }

        protected string UploadTempFile(HttpPostedFile postedFile)
        {
            if (ValidateFile(postedFile.FileName))
            {
                string path = this.Page.Server.MapPath(Sdk.Util.ConfigurationUtils.UploadPath);

                FormElement element = new FormElement(this.FormElementID, Alogient.Cameleon.Sdk.NavigationController.GetCultureCode());

                string tempFolder = string.Format("{0}/{1}_/", HttpContext.Current.Session.SessionID, DateTime.Now.ToString("yyyyMMddhhmmss"));
                string tempFolderPath = string.Format("{0}{1}", path, tempFolder);

                if (!Directory.Exists(tempFolderPath))
                    Directory.CreateDirectory(tempFolderPath);

                string tempFile = string.Format(UPLOAD_FORMAT, tempFolder, element.FormID, element.PageID, element.ID, ShortFileName(postedFile.FileName));

                string tempFilePath = string.Format("{0}{1}", path, tempFile);

                //string newFile = string.Format("{0}{1}", path, tempFile);

                postedFile.SaveAs(tempFilePath);

                return tempFile;
            }

            return string.Empty;
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            
            if (this.Page.IsPostBack)
            {
                FileUpload upload = this.FindControl(string.Format(UPLOAD_ID_FORMAT, this.ID)) as FileUpload;
                if (upload.Attributes["Uploaded"] == "false")
                {
                    //Create (if needed) the sessionID folder in FormMedia for TEMP file
                    //HttpContext.Current.Session.SessionID

                    //Upload the file with the Posted File format name
                    string tempFile = UploadTempFile(upload.PostedFile);

                    if (!string.IsNullOrEmpty(tempFile))
                    {
                        //this.PostedFile = upload.PostedFile;
                        upload.Attributes["Uploaded"] = "true";
                        upload.Attributes["TempFile"] = tempFile;
                        upload.Attributes["SessionID"] = HttpContext.Current.Session.SessionID;
                    }
                }
            }
        }

        protected string ShortFileName(string longFileName)
        {
            if (longFileName.IndexOf('\\') >= 0)
                return longFileName.Substring(longFileName.LastIndexOf('\\')+1);

            return longFileName;
        }

        public string UploadFile()
        {
            FileUpload fileUpload = this.FindControl(string.Format(UPLOAD_ID_FORMAT, this.ID)) as FileUpload;

            if (fileUpload.Attributes["Uploaded"].ToLower() == "true")
            {
                string path = this.Page.Server.MapPath(Sdk.Util.ConfigurationUtils.UploadPath);
                string tempFile = fileUpload.Attributes["TempFile"];
                string tempFilePath = string.Format("{0}{1}", path, tempFile);

                string newFilePath = tempFilePath.Remove(tempFilePath.LastIndexOf('/'), 1);
                newFilePath = newFilePath.Replace(string.Format("{0}/", fileUpload.Attributes["SessionID"]), string.Empty);

                if (File.Exists(tempFilePath))
                {
                    File.Move(tempFilePath, newFilePath);

                    CleanUploadFolder();

                    return newFilePath.Replace(path, string.Empty);
                }
                else
                {
                    return string.Empty;
                }
            }

            return string.Empty;
        }

        protected void CleanUploadFolder()
        {
            string path = this.Page.Server.MapPath(Sdk.Util.ConfigurationUtils.UploadPath);

            foreach (string directoryPath in Directory.GetDirectories(path))
            {
                if ((DateTime.Now - Directory.GetLastWriteTime(directoryPath)).Hours >= Util.ConfigurationUtils.TempFolderTTL)
                {
                    try
                    {
                        Directory.Delete(directoryPath);
                    }
                    catch (Exception) { }
                }
            }
        }

        internal FormUpload(Forms.Sdk.Items.Upload element) : base(element)
        {
            System.Web.UI.WebControls.FileUpload upload = new FileUpload();
            upload.ID = string.Format(UPLOAD_ID_FORMAT, this.ID);
            upload.Attributes["Uploaded"] = "false";

            Label label = new Label();
            label.Text = element.Label;
            label.CssClass = string.Format("{0}Label", element.CSS);

            #region Validators

            PlaceHolder phValidators = new PlaceHolder();
            
            if (element.Required)
            {
                Label redStar = new Label();
                redStar.ForeColor = Color.Red;
                redStar.Text = "*";
                phValidators.Controls.Add(redStar);

                RequiredFieldValidator required = new RequiredFieldValidator();
                required.ID = string.Format("required_{0}_{1}", element.FormID, element.ID);
                required.ControlToValidate = upload.ID;
                required.ValidationGroup = element.FormID.ToString();
                required.Display = ValidatorDisplay.Dynamic;
                required.ErrorMessage = string.Format(WebUtil.GetValidatorRessource("Required"), element.Label); 
    
                phValidators.Controls.Add(required);
            }

            CustomValidator validateFile = new CustomValidator();
            validateFile.ID = string.Format("validateFile_{0}_{1}", element.FormID, element.ID);
            validateFile.ControlToValidate = upload.ID;
            validateFile.ValidationGroup = element.FormID.ToString();
            validateFile.Display = ValidatorDisplay.Dynamic;
            validateFile.ErrorMessage = string.Format(WebUtil.GetValidatorRessource("UploadValidateFile_ErrorMessage"), element.Label); 
            validateFile.EnableClientScript = false;
            validateFile.ServerValidate += new ServerValidateEventHandler(validateFile_ServerValidate);
            
            phValidators.Controls.Add(validateFile);

            #endregion

            GenerateRow(element, label, upload, phValidators);
        }

        protected void validateFile_ServerValidate(object source, ServerValidateEventArgs args)
        {
            args.IsValid = ValidateFile(args.Value);
        }

        protected bool ValidateFile(string fileName)
        {
            FormElement element = new FormElement(this.FormElementID, Alogient.Cameleon.Sdk.NavigationController.GetCultureCode());

            string extension = System.IO.Path.GetExtension(fileName).ToLower().Replace(".", string.Empty);

            Items.Upload upload = new Items.Upload(element.ID, element.CultureCode);
            string bl = upload.FileTypeBlackList;
            string wl = upload.FileTypeWhiteList;

            //Whitelist Validation
            if (!string.IsNullOrEmpty(wl))
            {
                bool valid = false;
                string[] whiteList = wl.Split(',');
                foreach (string ext in whiteList)
                {
                    if (extension == ext)
                    {
                        valid = true;
                    }
                }

                if (!valid)
                {
                    //throw new Exception("File extension not in whitelist");

                    //args.IsValid = false;
                    return false;
                }
            }

            //Blacklist Validation
            if (!string.IsNullOrEmpty(bl))
            {
                string[] blackList = bl.Split(',');
                foreach (string ext in blackList)
                {
                    if (extension == ext)
                    {
                        //throw new Exception("File extension in blacklist");
                        //args.IsValid = false;
                        return false;
                    }
                }
            }

            //Default BlackList - exe, dll, aspx, ascx
            foreach (string ext in ConfigurationUtils.DefaultBlackList)
            {
                if (extension == ext)
                {
                    //throw new Exception("File extension in default blacklist");
                    //args.IsValid = false;
                    return false;
                }
            }

            return true;
        }


    }
}
